package com.zoran.study.spring.service;


import com.zoran.study.spring.helper.ApplicationContextHelper;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.AsyncResult;
import org.springframework.stereotype.Service;
import org.springframework.util.concurrent.ListenableFuture;

import java.util.Random;
import java.util.concurrent.Future;

/**
 * TaskService
 *
 * @author zouxm
 * @date 2018/4/3
 */
@Service
public class TaskService extends BaseService {
    private final Random random = new Random();

    //异步方法只能返回ListenableFuture or Future
    @Async
    public ListenableFuture<String> doTask1() throws InterruptedException {
        System.out.println(Thread.currentThread().getName() + "[do task1]");
        Thread.sleep(random.nextInt(5000));
        return new AsyncResult<>("success");
    }

    @Async
    public Future<Void> testExecutinException() {
        System.out.println(Thread.currentThread().getName() + "[do task1]");
        throw new RuntimeException("test exception");
    }

    @Async
    public void doTask2() throws InterruptedException {
        System.out.println(Thread.currentThread().getName() + "[do task2]");
//        this.doTask4();  //通过this调用,此时this表示的是目标对象(真实对象),不是代理对象,无法实现方法Aop增强
//        ApplicationContextHelper.getBean(TaskService.class).doTask4();
//        拿到spring代理对象调用,实现Aop增强,private方法没法实现AOP增强 两种方式:
//       1: ApplicationContextHelper.getBean(TaskService.class).doTask4();
//        2:通过开启@EnableAspectJAutoProxy(exposeProxy=true)实现在线程中拿到代理对象
//        TaskService taskService = AopContext.currentProxy() != null ? (TaskService) AopContext.currentProxy() : this;
        ApplicationContextHelper.getBean(TaskService.class).doTask4();
    }

    @Async
    public void doTask3() throws InterruptedException {
        System.out.println(Thread.currentThread().getName() + "[do task3]");
        Thread.sleep(random.nextInt(5000));
//        int i=5/0;
    }

    @Async
    public void doTask4() throws InterruptedException {
        System.out.println(Thread.currentThread().getName() + "[do task4]");
        Thread.sleep(random.nextInt(5000));
    }

    @Async
    public void doTask5() throws InterruptedException {
        System.out.println(Thread.currentThread().getName() + "[do task5]");
    }

    /**
     * 在一个类中互相调用多个方法情形 加不加@Async注解都会在一个线程中执行(区别是主线程还是新启动的线程)
     * 此例中 doTask6和doTask1会在一个线程中执行
     *
     * @throws InterruptedException
     */
    public void doTask6() throws InterruptedException {
        System.out.println(Thread.currentThread().getName() + "[do task6]");
        this.doTask1();
    }


    public void syncMethod() throws InterruptedException {
        System.out.println(Thread.currentThread().getName() + "[sync method]");
        this.doTask1();
    }

    public static void testStatic() {
        System.out.println("static method invoke...");
    }

}
